#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include "../utils/map2.h"
#include "../utils/base.h"

#define MAN_NAME_LEN 64
// typedef struct man_st
// {
//     char name[MAN_NAME_LEN];
//     size_t age;
// } man_t;

typedef struct man_st
{
    char *name;
    size_t age;
} man_t;

int man_name_equal(const void *key1, const void *key2)
{
    char *k1 = (char *)key1;
    char *k2 = (char *)key2;
    if (strcmp(k1, k2) == 0)
        return 1;
    return 0;
}

int man_foreach(const void *key, void *value, void *userdata)
{
    char *k = (char *)key;
    man_t *man = (man_t *)value;
    // printf("key:%s man: {name:%s,age:%ld}\n", k, man->name, man->age);
    return 0;
}

int num_foreach(const void *key, void *value, void *userdata)
{
    int *k = (int *)key;
    int *v = (int *)value;
    // printf("key:%d value:%d\n", *k, *v);
    // printf("key:%s man: {name:%s,age:%ld}\n", k, man->name, man->age);
    return 0;
}

#define MANS_LEN 10000000
#if 0
int main()
{
    map_t man_map = {0};
    man_t mans[MANS_LEN] = {0};
    map_init(&man_map, map_murmur_hash, man_name_equal, NULL);
    long long now0 = now_ms();
    for (size_t i = 0; i < MANS_LEN; i++)
    {
        sprintf(mans[i].name, "hero$%ld", i);
        mans[i].age = i;
        assert(map_put(&man_map, &mans[i].name, strlen(mans[i].name), &mans[i]) == 0);
    }
    long long now1 = now_ms();
    map_foreach(&man_map, man_foreach, NULL);
    long long now2 = now_ms();
    // map_used(&man_map);

    const char *name = "hero$27";
    man_t *ret = (man_t *)map_get(&man_map, (void *)name, strlen(name));
    long long now3 = now_ms();
    if (ret != NULL)
        printf("{ name:%s, age:%ld }\n", ret->name, ret->age);
    map_deinit(&man_map);

    printf("条数: %lld,插入用时(ms):%lld 遍历用时(ms):%lld 获取用时(ms):%lld\n", MANS_LEN, now1 - now0, now2 - now1, now3 - now2);
    return 0;
}
#else

man_t **mans_init()
{
    man_t **mans = (man_t **)calloc(MANS_LEN, sizeof(man_t *));
    if (mans == NULL)
    {
        // 处理内存分配失败的情况
        return NULL;
    }

    for (size_t i = 0; i < MANS_LEN; i++)
    {
        mans[i] = (man_t *)malloc(sizeof(man_t));
        if (mans[i] == NULL)
        {
            // 处理内存分配失败的情况
            // 这里应该释放之前分配的所有内存，然后返回 NULL
            for (size_t j = 0; j < i; j++)
            {
                free(mans[j]);
            }
            free(mans);
            return NULL;
        }
        mans[i]->name = (char *)malloc(MAN_NAME_LEN);
        if (mans[i]->name == NULL)
        {
            // 处理内存分配失败的情况
            // 这里应该释放之前分配的所有内存，然后返回 NULL
            for (size_t j = 0; j <= i; j++)
            {
                free(mans[j]->name); // 注意这里也要释放名字的内存
                free(mans[j]);
            }
            free(mans);
            return NULL;
        }
        sprintf(mans[i]->name, "hero$%ld", i);
        mans[i]->age = (int)i;
    }
    return mans;
}

void mans_deinit(man_t **mans)
{
    for (size_t i = 0; i < MANS_LEN; i++)
    {
        free(mans[i]->name);
        free(mans[i]);
    }
    free(mans);
}
int main()
{
    map_t man_map = {0};
    man_t **mans = mans_init();
    map_init(&man_map, map_murmur_hash, man_name_equal, NULL);
    printf("malloc finish!\n");
    long long now0 = now_ms();
    for (size_t i = 0; i < MANS_LEN; i++)
    {
        // printf("now puts %s\n", mans[i]->name);
        assert(map_put(&man_map, mans[i]->name, strlen(mans[i]->name), mans[i]) == 0);
    }
    printf("puts finish!\n");
    long long now1 = now_ms();
    map_foreach(&man_map, man_foreach, NULL);
    long long now2 = now_ms();

    map_used(&man_map);
    long long now3 = now_ms();
    char name[MAN_NAME_LEN] = {0};
    for (size_t i = 0; i < MANS_LEN; i++)
    {
        sprintf(name, "hero$%ld", i);
        man_t *ret = (man_t *)map_get(&man_map, (void *)name, strlen(name));
        // if (ret != NULL)
        //     printf("{ name:%s, age:%ld }\n", ret->name, ret->age);
        if (ret == NULL)
            printf("name :%s not found\n", name);
    }
    long long now4 = now_ms();
    for (size_t i = 0; i < MANS_LEN; i++)
    {
        sprintf(name, "hero$%ld", i);
        map_del(&man_map, (void *)name, strlen(name));
    }
    long long now5 = now_ms();

    // map_enlarging_forced(&man_map);
    map_used(&man_map);
    map_deinit(&man_map);
    long long now6 = now_ms();
    mans_deinit(mans);
    long long now7 = now_ms();
    printf("条数: %d,插入用时(ms):%lld 遍历用时(ms):%lld 获取用时(ms):%lld 删除用时(ms):%lld deinit()用时(ms):%lld\n", MANS_LEN, now1 - now0, now2 - now1, now4 - now3, now5 - now4, now7 - now6);
    return 0;
}
#endif